/*  
     PlAr is Platform Arena: a 2D multiplayer shooting game
     Copyright (C) 2009 Ragagnin Antonio <spocchio@gmail.com>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package plar.core;

import java.awt.Point;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.List;

import plar.core.defaultElements.Player;

//import dynamics.World; 
//import dynamics.WorldListener;
//import collision.*;
//import common.*;

public class Level implements Runnable {

	public ActionManager actions;
	public List<Element> elements;
	// CollisionManager collisionManager;
	public Parameters info;
	//public World m_world;
	public List<Element> queueRemove;

	
	public Level() {
		
		//AABB m_worldAABB = new AABB();
		//m_worldAABB.lowerBound.set(-200.0f, -100.0f);
		//m_worldAABB.upperBound.set(200.0f, 200.0f);
		//Vec2 gravity = new Vec2(0.0f, -10.0f);
		boolean doSleep = true;
		//World m_world = new World(m_worldAABB, gravity, doSleep);
		elements = new ArrayList<Element>();
		actions = new ActionManager();
		// collisionManager = new CollisionManager();
		info = new Parameters();
		info.put("subAction", "main");
		info.put("level", this);
		queueRemove = new ArrayList<Element>();
		class Gravity implements Action {

			class ActionGravity implements Action {
				float gravity;
				int times;

				public ActionGravity(float g) {
					gravity = g;
					times = 0;
				}

				public Parameters call(Parameters parameters) {
					Element e = (Element) parameters.get("me");
					String a = (String) parameters.get("subAction");
					if (a == "main")
						if (e != null
								&& !e.canCollide(new Point(0, (int) gravity))) {

							// Point s = (Point)e.getProperty(".speed");
							// Point newDotSpeed= new
							// Point(s.x,s.y+(int)gravity*(times+1));
							// Point newDotSpeed= new
							// Point(s.x,s.y+(int)gravity);
							// Common.info("falling with: "+e+" "+times+" "+newDotSpeed.y);
							// e.setProperty(".speed", newDotSpeed);
							// times++;
							Point s = e.getSpeed();
							s.y += gravity;
							e.setSpeed(s);

						} else {
							// Common.info("stop falling: "+e);
							times = 0;
						}
					return null;
				}
			}

			float gravity;

			public Gravity(float g) {
				gravity = g;

			}

			public Parameters call(Parameters parameters) {

				for (Element e : ((Level) parameters.get("level")).getGravities()) {
					if (!e.actions.hasAction("gravity")) {
						e.actions.addAction("gravity", new ActionGravity(
								gravity));

					}
				}
				return null;
			}
		}

		actions.addAction("gravity", new Gravity(1));

	}

	public void AddElement(Element e) {
		elements.add(e);
		e.level = this;
		// collisionManager.addCollisionList(e);
	}

	public boolean canCollide(Rectangle r, Element e) {

		// Common.info("canCollidE? "+r);
		for (Element e1 : elements) {
			// Common.info(""+(Boolean)e1.getProperty("canCollide")+" rect:"+e1.getRectangle()+" ->"+e1.getRectangle().intersects(r));
			if ((Boolean) e1.getProperty("canCollide")
					&& e1.getRectangle().intersects(r)
					&& !((ArrayList<Element>) e1.getProperty("friendlyList"))
							.contains(e) && e1 != e) {

				return true;
			}

		}

		return false;
	}

	public void delElement(Element p) {

		queueRemove.add(p);

	}

	public ArrayList<Element> getCollisions(Element e, Rectangle r) {
		ArrayList<Element> collisions = new ArrayList<Element>();
		for (Element e1 : elements) {

			if ((Boolean) e1.getProperty("canCollide")
					&& e1.getRectangle().intersects(r)
					&& !((ArrayList<Element>) e1.getProperty("friendlyList"))
							.contains(e) && e1 != e) {

				collisions.add(e1);
			}

		}

		return collisions;
	}

	public ArrayList<Element> getElementsByType(String s) {
		ArrayList<Element> l = new ArrayList<Element>();
		for (Element e : elements) {
			if ((String) e.getProperty("type") == s)
				l.add(e);
		}

		return l;
	}

	public ArrayList<Player> getPlayers() {
		ArrayList<Player> l = new ArrayList<Player>();
		for (Element e : elements) {
			if (e.getProperty("type") == "player")
				l.add((Player) e);
		}

		return l;
	}

public ArrayList<Element> getGravities() {
		ArrayList<Element> l = new ArrayList<Element>();
		for (Element e : elements) {
			if ((Boolean)e.getProperty("hasGravity") == true)
				l.add(e);
		}

		return l;
	}

	public ArrayList<Element> getRunnable() {
		ArrayList<Element> inside = new ArrayList<Element>();
		for (Element e : elements) {
			if ((Boolean) e.getProperty("isRunnable"))
				inside.add(e);
		}
		return inside;
	}

	public ArrayList<Element> getScreen(Rectangle r0) {
		ArrayList<Element> inside = new ArrayList<Element>();
		for (Element e : elements) {
			Rectangle r = new Rectangle();
			r.x = e.getPosition().x - 1;
			r.y = e.getPosition().y - 1;
			r.width = e.getSize().x + 1;
			r.height = e.getSize().y + 1;
			if (r0.intersects(r))
				inside.add(e);
		}
		return inside;
	}

	public void run() {
	actions.runAll(info);
		// Common.info("elementi: "+elements.size());
		for (Element e : getRunnable()) {
			//Thread t = new Thread(e);
			e.run();
			//t.start();

		}
		for (Element e : queueRemove) {
			elements.remove(e);

		}
		queueRemove.clear();

	

	}

}
